package com.airbnb.airpal.resources;
import com.airbnb.airpal.api.Job;
import com.airbnb.airpal.api.JobState;
import com.airbnb.airpal.api.queries.CreateSavedQueryBuilder;
import com.airbnb.airpal.api.queries.SavedQuery;
import com.airbnb.airpal.api.queries.UserSavedQuery;
import com.airbnb.airpal.core.AirpalUser;
import com.airbnb.airpal.core.AuthorizationUtil;
import com.airbnb.airpal.core.store.history.JobHistoryStore;
import com.airbnb.airpal.core.store.queries.QueryStore;
import com.airbnb.airpal.presto.PartitionedTable;
import com.airbnb.airpal.presto.Table;
import com.facebook.presto.client.Column;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.inject.Inject;
import org.joda.time.DateTime;
import org.secnod.shiro.jaxrs.Auth;
import javax.annotation.Nullable;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
@Path("/api/query")
public class QueryResource
{
private final JobHistoryStore jobHistoryStore;
private final QueryStore queryStore;
@Inject
public QueryResource(JobHistoryStore jobHistoryStore,
QueryStore queryStore)
{
this.jobHistoryStore = jobHistoryStore;
this.queryStore = queryStore;
}
@GET
@Path("saved")
@Produces(MediaType.APPLICATION_JSON)
public Response getSaved(
@Auth AirpalUser user,
@QueryParam("table") List<PartitionedTable> tables)
{
if (user != null) {
return Response.ok(queryStore.getSavedQueries(user)).build();
}
return Response.ok(Collections.<SavedQuery>emptyList()).build();
}
@POST
@Path("saved")
@Produces(MediaType.APPLICATION_JSON)
public Response saveQuery(
@Auth AirpalUser user,
@FormParam("description") String description,
@FormParam("name") String name,
@FormParam("query") String query)
{
CreateSavedQueryBuilder createFeaturedQueryRequest = CreateSavedQueryBuilder.featured()
.description(description)
.name(name)
.query(query);
if (user != null) {
SavedQuery savedQuery = createFeaturedQueryRequest.user(user.getUserName())
.build();
if (queryStore.saveQuery((UserSavedQuery) savedQuery)) {
return Response.ok(savedQuery.getUuid()).build();
}
else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
return Response.status(Response.Status.UNAUTHORIZED).build();
}
@DELETE
@Path("saved/{uuid}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteQuery(
@Auth AirpalUser user,
@PathParam("uuid") UUID uuid)
{
if (user != null) {
if (queryStore.deleteSavedQuery(user, uuid)) {
return Response.status(Response.Status.NO_CONTENT).build();
}
else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
return Response.status(Response.Status.UNAUTHORIZED).build();
}
public static Function<Job, DateTime> JOB_ORDERING = new Function<Job, DateTime>()
{
@Nullable
@Override
public DateTime apply(@Nullable Job input)
{
if (input == null) {
return null;
}
return input.getQueryFinished();
}
};
@GET
@Path("history")
@Produces(MediaType.APPLICATION_JSON)
public Response getHistory(
@Auth AirpalUser user,
@QueryParam("table") List<Table> tables)
{
Iterable<Job> recentlyRun;
if (tables.size() < 1) {
recentlyRun = jobHistoryStore.getRecentlyRun(200);
}
else {
Table[] tablesArray = tables.toArray(new Table[tables.size()]);
Table[] restTables = Arrays.copyOfRange(tablesArray, 1, tablesArray.length);
recentlyRun = jobHistoryStore.getRecentlyRun(200, tablesArray[0], restTables);
}
ImmutableList.Builder<Job> filtered = ImmutableList.builder();
for (Job job : recentlyRun) {
if (job.getTablesUsed().isEmpty() && (job.getState() == JobState.FAILED)) {
filtered.add(job);
continue;
}
for (Table table : job.getTablesUsed()) {
if (AuthorizationUtil.isAuthorizedRead(user, table)) {
filtered.add(new Job(
job.getUser(),
job.getQuery(),
job.getUuid(),
job.getOutput(),
job.getQueryStats(),
job.getState(),
Collections.<Column>emptyList(),
Collections.<Table>emptySet(),
job.getQueryStartedDateTime(),
job.getError(),
job.getQueryFinishedDateTime()));
}
}
}
List<Job> sortedResult = Ordering
.natural()
.nullsLast()
.onResultOf(JOB_ORDERING)
.reverse()
.immutableSortedCopy(filtered.build());
return Response.ok(sortedResult).build();
}
}